////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_MATH_BOX_H__
#define __WN_MATH_BOX_H__

#include "WNCore/inc/WNTypes.h"
#include "WNMath/inc/WNPoint3.h"
#include "WNMath/inc/WNVector3.h"
#include "WNMath/inc/WNQuaternion.h"

namespace WNMath {
    class WNBounds3;
    class WNSphere;

    class WNBox {
    public:
        WNBox();
        explicit WNBox(const WN_FLOAT32* _f);
        explicit WNBox(const WNPoint3& _location, const WNVector3& _extents, const WNQuaternion& _rotation);
        explicit WNBox(const WNPoint3& _point);

        WN_BOOL operator == (const WNBox& _rectangle) const;
        WN_BOOL operator != (const WNBox& _rectangle) const;

        WN_VOID Zero();
        WN_VOID Expand(WN_FLOAT32 _amount);
        WN_BOOL Expand(const WNPoint3& _point, WN_BOOL _anchor = WN_FALSE);
        WN_BOOL Expand(const WNSphere& _sphere, WN_BOOL _anchor = WN_FALSE);
        WN_BOOL Expand(const WNBounds3& _bounds, WN_BOOL _anchor = WN_FALSE);
        WN_BOOL Expand(const WNBox& _box, WN_BOOL _anchor = WN_FALSE);
        WN_VOID Translate(WN_FLOAT32 _x, WN_FLOAT32 _y, WN_FLOAT32 _z);
        WN_VOID Translate(const WNVector3& _vector);
        WN_VOID Rotate(const WNQuaternion& _rotation);
        WN_VOID Scale(WN_FLOAT32 _scale);
        WN_VOID Scale(WN_FLOAT32 _x, WN_FLOAT32 _y, WN_FLOAT32 _z);
        WN_VOID Scale(const WNVector3& _scale);
        
        WN_FLOAT32 Length() const;
        WN_FLOAT32 Width() const;
        WN_FLOAT32 Height() const;
        WN_FLOAT32 SurfaceArea() const;
        WN_FLOAT32 Volume() const;

        WN_BOOL IsZero() const;
        WN_BOOL IsInsideOut() const;

        WN_VOID Set(const WN_FLOAT32* _f);
        WN_VOID Set(const WNPoint3& _location, WNVector3& _extents, const WNQuaternion& _rotation);
        WN_VOID Set(const WNPoint3& _point);

        WNBox GetExpanded(WN_FLOAT32 _amount) const;
        WNBox GetExpanded(const WNPoint3& _point, WN_BOOL _anchor = WN_FALSE) const;
        WNBox GetExpanded(const WNSphere& _sphere, WN_BOOL _anchor = WN_FALSE) const;
        WNBox GetExpanded(const WNBounds3& _bounds, WN_BOOL _anchor = WN_FALSE) const;
        WNBox GetExpanded(const WNBox& _box, WN_BOOL _anchor = WN_FALSE) const;
        WNBox GetTranslated(WN_FLOAT32 _x, WN_FLOAT32 _y, WN_FLOAT32 _z);
        WNBox GetTranslated(const WNVector3& _vector) const;
        WNBox GetRotated(const WNQuaternion& _rotation) const;
        WNBox GetScaled(WN_FLOAT32 _scale) const;
        WNBox GetScaled(WN_FLOAT32 _x, WN_FLOAT32 _y, WN_FLOAT32 _z) const;
        WNBox GetScaled(const WNVector3& _scale) const;
        WN_VOID GetPoints(WNPoint3* _points) const;

    public:
        WNPoint3 mLocation;
        WNVector3 mExtents;
        WNQuaternion mRotation;
    };
}

#endif // __WN_MATH_BOX_H__